#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <limits.h>
#include <dirent.h>
#include <sys/time.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <pwd.h>

#include "data_type.h"
#include "cube.h"
#include "cube_define.h"
#include "cube_record.h"

#include "json.h"

#include "shell_list.h"
#include "cmdlist_read.h"

#define MAX_LINE_LEN 1024

static unsigned char Buf[DIGEST_SIZE*32];

int cmdlist_read_init(void * sub_proc,void * para)
{
    int ret;

    return 0;
}

int cmdlist_read_start(void * sub_proc,void * para)
{
    		
    int ret = 0, len = 0, i = 0, j = 0;
    int rc = 0;
    struct start_para * start_para = para;

    int type,subtype;	

    void * recv_msg;

    if(para!=NULL)
    {
		if(start_para->argc >=2)
	    {
			for(i=1;i<start_para->argc;i++)
			{
				ret=proc_cmdlist_read(sub_proc,start_para->argv[i],NULL);
			}
    	}
	}

    while(1)
    {
        usleep(time_val.tv_usec);

		ret=ex_module_recvmsg(sub_proc,&recv_msg);
		if(ret<0)
			continue;
		if(recv_msg==NULL)
			continue;
		type=message_get_type(recv_msg);
		subtype=message_get_subtype(recv_msg);
		if(!memdb_find_recordtype(type,subtype))
		{
			printf("message format (%d %d) is not registered!\n",
			message_get_type(recv_msg),message_get_subtype(recv_msg));
			continue;
		}
		if((type==TYPE(GENERAL_RETURN))&&(subtype==SUBTYPE(GENERAL_RETURN,STRING)))
		{
			ret=proc_cmdlist_readfrommsg(sub_proc,recv_msg);
		}
	}
    return 0;
}

void * proc_cmdunit_read(RECORD(SHELL_LIST,CMD_SET) * cmd_set, void * unit_node,int seq_no)
{
		int ret;
		void * elem_node;
		char * cmd_line;
		int delay;
		char * cmd_desc;
		RECORD(SHELL_LIST,CMD_UNIT) * cmd_unit;
		cmd_unit = Talloc0(sizeof(*cmd_unit));
		if(cmd_unit ==NULL)
				return NULL;


		elem_node = json_find_elem("cmd_line",unit_node);
		if(elem_node==NULL)
		{
				print_cubeerr("cmdlist_read: cmd unit has no cmd_line!");
				Free(cmd_unit);
				return NULL;	
		}	
		cmd_line=json_get_valuestr(elem_node);
		cmd_unit->cmd_line = dup_str(cmd_line,256);

		elem_node = json_find_elem("delay",unit_node);
		if(elem_node !=NULL)
		{
			ret = json_node_getvalue(elem_node,&delay,sizeof(delay));
			cmd_unit->delay=delay;
		}	

		elem_node = json_find_elem("cmd_desc",unit_node);
		if(elem_node !=NULL)
		{
			cmd_desc=json_get_valuestr(elem_node);
			cmd_unit->cmd_desc = dup_str(cmd_desc,128);
		}	

		cmd_unit->seq_no=seq_no;
		cmd_unit->item_name = dup_str(cmd_set->item_name,DIGEST_SIZE*2);
		cmd_unit->set_name = dup_str(cmd_set->set_name,DIGEST_SIZE*2);

		return cmd_unit;

}

int proc_cmdlist_read(void * sub_proc,char * file_name, void * recv_msg)
{
    int ret;
    int i=0;
    void * send_msg;
	int fd;
	char * buffer;
	void * root_node;
	void * set_node;
	void * list_node;
	void * unit_node;
	void * elem_node;
	char * item_name;
	char * set_name;
	char * temp_str;
	RECORD(SHELL_LIST,CMD_UNIT) * cmd_unit;
	RECORD(SHELL_LIST,CMD_SET) * cmd_set;

	/*
	buffer =Talloc0(2048);
	if(buffer == NULL)
			return -ENOMEM;
			*/
	fd = open(file_name,O_RDONLY);
	if(fd<0)
			return fd;

	// 第一个json项为item名称及描述
	ret= read_json_node(fd,&root_node);
	if(ret>0)
	{
		elem_node = json_find_elem("item_name",root_node);
		if(elem_node==NULL)
		{
				print_cubeerr("cmdlist_read: cmd file %s has no item_name!",file_name);
				close(fd);
				return -EINVAL;	
		}	
		item_name=json_get_valuestr(elem_node);
		if(item_name==NULL)
		{
				print_cubeerr("cmdlist_read: file %s has invalid item_name!",file_name);
				close(fd);
				return -EINVAL;	
		}
	}
  
    // 后续json项均为cmd_set的描述
	
	ret= read_json_node(fd,&root_node);

	int seq_no=0;
	int cmd_num;

	while(root_node != NULL)
	{
			cmd_set = Talloc0(sizeof(*cmd_set));
			if(cmd_set ==NULL)
					return -ENOMEM;
			cmd_set->item_name = dup_str(item_name,DIGEST_SIZE*2);
			// get set_name from json
			elem_node = json_find_elem("set_name",root_node);
			if(elem_node == NULL)
			{
					print_cubeerr("cmdlist_read: file %s can't find set_name",file_name);
					return -EINVAL;
			}
			set_name = json_get_valuestr(elem_node);
			cmd_set->set_name = dup_str(set_name,DIGEST_SIZE*2);

			elem_node = json_find_elem("seq_no",root_node);
			if(elem_node !=NULL)
			{
				ret = json_node_getvalue(elem_node,&seq_no,sizeof(seq_no));
				cmd_set->seq_no = seq_no;
			}	
			else
			{
					seq_no++;
					cmd_set->seq_no=seq_no;
			}
			
			elem_node = json_find_elem("delay",root_node);
			if(elem_node !=NULL)
			{
				temp_str=json_get_valuestr(elem_node);
				cmd_set->delay = Atoi(temp_str,DIGEST_SIZE);
			}	

			elem_node = json_find_elem("cmdset_desc",root_node);
			if(elem_node !=NULL)
			{
				temp_str=json_get_valuestr(elem_node);
				cmd_set->cmdset_desc = dup_str(temp_str,128);
			}	
			
			cmd_num=0;
			set_node = json_find_elem("cmd_set",root_node);
			if(set_node == NULL)
			{
					print_cubeerr("cmdlist_read: no cmd exist!");
					return -EINVAL;
			}
			unit_node=json_get_first_child(set_node);
			while(unit_node != NULL)
			{
				cmd_num++;	
				cmd_unit = proc_cmdunit_read(cmd_set,unit_node,cmd_num);
				if(cmd_unit == NULL)
				{
					print_cubeerr("cmdlist_read: solve cmdset %s  unit %s error!",
									cmd_set->set_name,cmd_num);
					return -EINVAL;
				}	
				memdb_store(cmd_unit,TYPE_PAIR(SHELL_LIST,CMD_UNIT),NULL);
				unit_node=json_get_next_child(set_node);
			}
			cmd_set->cmd_num = cmd_num;

			memdb_store(cmd_set,TYPE_PAIR(SHELL_LIST,CMD_SET),NULL);

			ret= read_json_node(fd,&root_node);
	}
/*		
	if(recv_msg != NULL)
	{
        	send_msg=message_create(TYPE_PAIR(SHELL_LIST,CMD_SET),NULL);
        	if(send_msg==NULL)
           		return -EINVAL;
	}
   	message_add_record(send_msg,shell_notice);
   	ex_module_sendmsg(sub_proc,send_msg);
*/

    void * types_msg;
    types_msg = message_gen_typesmsg(TYPE_PAIR(SHELL_LIST,CMD_SET),NULL);
    if(types_msg==NULL)
	    return -EINVAL;
    ex_module_sendmsg(sub_proc,types_msg);
    sleep(1);
    types_msg = message_gen_typesmsg(TYPE_PAIR(SHELL_LIST,CMD_UNIT),NULL);
    if(types_msg==NULL)
	    return -EINVAL;
    ex_module_sendmsg(sub_proc,types_msg);

    return 0; 
}

int proc_cmdlist_readfrommsg (void * sub_proc,void * recv_msg)
{
    int ret;
    int i=0;
    void * send_msg;
    RECORD(GENERAL_RETURN,STRING) * cmd_file;

    char policy_type[DIGEST_SIZE];
    char policy_path[DIGEST_SIZE*4];

    ret = message_get_record(recv_msg,&cmd_file,0);
    if(ret<0)
        return ret;

	return proc_cmdlist_read(sub_proc,cmd_file->return_value,recv_msg);
}
